﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.Web;
using System.Web.Mvc;
using System.Reflection;

namespace Q42.Wheels.Mvc.Paging.Utils
{
  /// <summary>
  /// Some usefull Dictionary Utility methods
  /// </summary>
  public static class DictionaryUtils
  {
    /// <summary>
    /// Get a RouteValueDictionary filled with the required values for a paging call
    /// </summary>
    /// <param name="viewContext"></param>
    /// <param name="paging"></param>
    /// <param name="page"></param>
    /// <param name="sortField"></param>
    /// <returns></returns>
    public static RouteValueDictionary GetRouteDataForLink(ViewContext viewContext, Paging paging, int? page, string sortField)
    {
      RouteValueDictionary newDict = DictionaryUtils.GetCompleteRouteData(viewContext.RouteData.Values, viewContext.RequestContext.HttpContext);
      if (!String.IsNullOrWhiteSpace(paging.Sort))
      {
        newDict[paging.SortParameterName] = paging.Sort;
      }

      if (page.HasValue)
        if (page.Value == 0)
          newDict.Remove(paging.PageParameterName);
        else
          newDict[paging.PageParameterName] = page.Value;

      if (!String.IsNullOrWhiteSpace(sortField))
      {
        if (!paging.KeepPageAfterSort)
          newDict.Remove(paging.PageParameterName);

        if (newDict.Keys.Contains(paging.SortParameterName))
        {
          if (newDict[paging.SortParameterName].ToString() == sortField)
          {
            if (newDict[paging.SortDescendingParameterName] == null)
              newDict[paging.SortDescendingParameterName] = 1;
            else
              newDict.Remove(paging.SortDescendingParameterName);
          }
          else
          {
            newDict[paging.SortParameterName] = sortField;
            newDict.Remove(paging.SortDescendingParameterName);
          }
        }
        else
        {
          newDict[paging.SortParameterName] = sortField;
        }
      }

      if (paging.VaryByParamsValues != null)
      {
        foreach (string param in paging.VaryByParamsValues.Keys)
        {
          newDict[String.Format("{0}.{1}", paging.PagingName, param)] = paging.VaryByParamsValues[param];
        }
      }

      return newDict;
    }

    /// <summary>
    /// Get all current RouteData (regular and GET)
    /// </summary>
    /// <param name="dict"></param>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static RouteValueDictionary GetCompleteRouteData(RouteValueDictionary dict, HttpContextBase httpContext)
    {
      RouteValueDictionary newDict = new RouteValueDictionary(dict);

      foreach (string key in httpContext.Request.Form.Keys)
      {
        newDict[key] = httpContext.Request.Form[key];
      }

      foreach (string key in httpContext.Request.QueryString.Keys)
      {
        // Hack: Only skip the Mvc generated Ajax query param
        if (key != "X-Requested-With")
          newDict[key] = httpContext.Request.QueryString[key];
      }

      return newDict;
    }

    /// <summary>
    /// Convert anonymous object to IDictionary
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static IDictionary<string, object> AnonymousObjectToDictionary(object obj)
    {
      return obj == null ? new Dictionary<string, object>() : obj.GetType().GetProperties().ToDictionary(o => o.Name, o => o.GetValue(obj, null));
    }
  }
}
